﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LNUGame.Model;
using LNUGame.View;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace LNUGame.Controller
{
    /// <summary>
    /// Controls everything related to the gameplay.
    /// </summary>
    class GameController : IController
    {
        private GameModel m_model;
        private GameInputHandler m_inputHandler;
        private GameSound m_sound;
        private GameView m_view;
        private Camera m_camera;

        private bool m_changeController;
        private bool m_startNewGame;

        private float m_timer = 0.0f;

        /// <summary>
        /// Main constructor.
        /// Creates instances to control the view, sound, camera, input and gameplay.
        /// </summary>
        /// <param name="a_manager">The GraphicsDeviceManager to use</param>
        /// <param name="a_contentManager">The ContentManager to use</param>
        public GameController(GraphicsDeviceManager a_manager, ContentManager a_contentManager)
        {
            m_model = new GameModel();
            m_sound = new GameSound(a_contentManager);
            m_view = new GameView(a_manager, a_contentManager);
            m_camera = new Camera();
            m_inputHandler = new GameInputHandler();
        }

        /// <summary>
        /// If the game is playing controls what keys the user is pressing and relays them to the model.
        /// If the player is dead, show a game over screen.
        /// If the player finished a level, shows a end of level screen.
        /// Updates the model.
        /// </summary>
        /// <param name="a_elapsedTime">How long time since the game was started</param>
        public void Update(float a_elapsedTime)
        {
            if (m_model.GetGameState() == GameModel.GameState.PLAYING)
            {
                if (!m_sound.RainSoundIsPlaying)
                {
                    m_sound.StartAmbientRain();
                }

                if (m_inputHandler.DidPlayerPressEsc())
                {
                    if (m_sound.RainSoundIsPlaying)
                    {
                        m_sound.StopAmbientRain();
                    }
                    m_changeController = true;
                }
                if (m_inputHandler.DidPlayerPressRight())
                {
                    m_model.MoveRight();
                }
                if (m_inputHandler.DidPlayerPressLeft())
                {
                    m_model.MoveLeft();
                }
                if (m_inputHandler.DidPlayerPressJump())
                {
                    m_model.DoJump();
                }
            }
            else if (m_model.GetGameState() == GameModel.GameState.PLAYER_DEAD)
            {
                if (m_sound.RainSoundIsPlaying)
                {
                    m_sound.StopAmbientRain();
                }
                while (m_timer < 3.0f)
                {
                    m_timer += a_elapsedTime;
                    return;
                }
                m_timer = 0.0f;
                m_changeController = true;
            }
            else if (m_model.GetGameState() == GameModel.GameState.FINISHED_LEVEL)
            {
                if(m_model.GetLevel().CurrentLevel == Level.Levels.LAST)
                {
                    m_model.SetGameState(GameModel.GameState.FINISHED_LAST_LEVEL);
                }

                if (m_sound.RainSoundIsPlaying)
                {
                    m_sound.StopAmbientRain();
                }
                while (m_timer < 3.0f)
                {
                    m_timer += a_elapsedTime;
                    return;
                }
                m_timer = 0.0f;
                m_model.LoadNextLevel();
                while (!m_sound.RainSoundIsPlaying)
                {
                    m_sound.StartAmbientRain();
                }
            }
            else if (m_model.GetGameState() == GameModel.GameState.FINISHED_LAST_LEVEL)
            {
                if (m_sound.RainSoundIsPlaying)
                {
                    m_sound.StopAmbientRain();
                }
                while (m_timer < 3.0f)
                {
                    m_timer += a_elapsedTime;
                    return;
                }
                m_timer = 0.0f;
                m_changeController = true;
            }

            for (int i = 0; i < 10; i++)
            {
                m_model.Update(a_elapsedTime/10, m_sound, m_view);
            }
        }

        /// <summary>
        /// Focuses the camera on the player and updates the view.
        /// </summary>
        /// <param name="a_elapsedTime">How long time since the game was started</param>
        /// <param name="a_graphicsDevice"></param>
        public void Draw(float a_elapsedTime, GraphicsDevice a_graphicsDevice)
        {
            m_camera.CenterOn(m_model.GetPlayerPosition(),
                              new Vector2(a_graphicsDevice.Viewport.Width, a_graphicsDevice.Viewport.Height),
                              new Vector2(Level.LEVEL_WIDTH, Level.LEVEL_HEIGHT)
                              );

            m_view.DrawGame(a_elapsedTime,
                            a_graphicsDevice,
                            m_camera,
                            m_model.GetLevel(),
                            m_model.GetPlayerPosition(),
                            m_model.GetPlayerRemainingLives(),
                            m_model.GetPlayerDirection(),
                            m_model.GetEnemyPositions(),
                            m_model.GetEnemyDirections(),
                            m_model.GetHealthpackPositions(),
                            m_model.GetGameState()
                            );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns>True if the controller changed, false otherwise</returns>
        public bool DidPlayerChangeController()
        {
            bool b = m_changeController;
            m_changeController = false;
            return b;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns>True if a new game should be started, false otherwise</returns>
        public bool StartNewGame()
        {
            bool b = m_startNewGame;
            m_startNewGame = false;
            return b;
        }
    }
}
